// Fractal Brownian Motion Modulator

import java.util.Random;

Random rnd = new Random();
int maxLevel = 10;
float[] X = new float[round(pow(2, maxLevel))+1];

float[] delta = new float[maxLevel+1];

float sigma; // standart deviation

void fbm(float H, long seed) {
  rnd.setSeed(seed);
  for (int i = 1; i <= maxLevel; i++) {
    delta[i] = sigma * pow(0.5, i*H)*sqrt(0.5)*sqrt(1-pow(2, 2*H-2));
  }
  int N = round(pow(2, maxLevel));
  X[0] = 0;
  X[N] = sigma * (float) rnd.nextGaussian();
  int D = N;
  int d = D/2;
  int level = 1;
  while (level<=maxLevel) {
    //println(level);
    for (int i = d; i <= N-d; i+=D) {
      X[i] = 0.5 * (X[i-d]+X[i+d]);
    }
    for (int i = 0; i <= N; i+=d) {
      X[i] = X[i] + delta[level]* (float)rnd.nextGaussian();
    }
    D = D/2;
    d = d/2;
    level++;
  }
}

void setupFbm(float sigma_, int size){
    sigma = sigma_;
    Double tmp = (Math.log(size-1)/Math.log(2));
    maxLevel = tmp.intValue();
    X = new float[round(pow(2, maxLevel))+1];
    delta = new float[maxLevel+1];
}

